//重新声明命名空间？
//类似objective-c中的？类是在别的地方定义的，在这只是要使用，直接声明一个同样名字的类？
AutodeskNamespace("Autodesk.ADN.Viewing.Extension");
var publicPath = '.'
var annotation = function(viewer){

    var ModeEnum = {
        kModeIddle: 0,
        kModeInitDrag: 1,
        kModeDrag: 2
    };

    const panelW = 400;
    const panelH = 600;

    var _mode = ModeEnum.kModeIddle;

    var _selectedMarkUpId = null;

    var _currentMarkUp = null;

    var _propComboId = null;

    var _markUps = {};

    var _self = this;

    _self._markUps = _markUps;

    var _propName = '';

    var _contentDiv = 
		`
		<div class="drawingLabelDiv" style="width: 300px; height: 80px; background-color: #fff; position:absolute; pointer-events: all; display: ''">
			<textarea class="form-control" style="width:200px;height:66px;resize:none;float:left;font-size:12px;"></textarea>
			<div>
                <button id='share' class="btn btn-info" style=" bottom: 0px; right: 0px; width:46px; height:20px; ">分享</button><br>
                <button id='submit' class="btn btn-primary" style=" bottom: 0px; right: 0px; width:46px; height:20px; ">确认</button><br>
                <button id='delete' class="btn btn-danger" style=" top: 0px; right: 0px; width:46px; height:20px; ">删除</button>
			</div>
		</div>
		`;

        // <button id='submit' style=" bottom: 0px; right: 0px; width:46px; height:20px; background-color: #dbffde;">确认</button><br>
        // <button id='edit' style=" bottom: 0px; right: 0px; width:46px; height:20px; background-color: #dbe2ff;">修改</button><br>
        // <button id='delete' style=" top: 0px; right: 0px; width:46px; height:20px; background-color: #ffdbdb;">删除</button>
    //add by cz begin
    /*
        [function]  addMarker <function>    : add a new marker to viewer
        [parameter] data      <json>        :            
            .attachmentPoint     : 3d point, in the viewer.     vector3
            .pointImgUrl         : point img                    string
            .mid                 : mark id                      string
            .text                : mark display text            string
            .deleteActive        : delete button active         0,1
    */
    _self.addMarker = function(data){
        //new a markup
        let makeUp = newMarkUp(data.attachmentPoint, data.pointImgUrl, data.mid, data.text, data.deleteActive, data.shareActive);

        // $('#' + _currentMarkUp.divId).css({'visibility': 'visible'});
        _markUps[makeUp.divId] = makeUp;

        viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, _self.onCameraChanged);

        _self.updateMarkUps();
    }

    /*
        [function]  enableEdit  <function> : change the edit made
    */
    _self.enableEdit = function(){
        $(viewer.container). bind("click", _self.onMouseClick);
    }

    _self.disableEdit = function(){
        $(viewer.container).unbind("click", _self.onMouseClick);
        _currentMarkUp = null;
    }

    _self.getMarkerData = function(){
        return {
            // dbId : _currentMarkUp.dbId,
            // fragId : _currentMarkUp.fragId,
            attachmentPoint : _currentMarkUp.attachmentPoint,
        };
    }

    _self.clear = function(){
        _markUps = {};
        updateMarkUps();
    }

    ///////////////////////////////////////////////////////////////////////////
    // load callback
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.load = function (htmlContent) {
        function activateAnnotate() {
            viewer.setPropertyPanel(null);
        }

        // context menu stuff

        Autodesk.ADN.Viewing.Extension.MarkUpContextMenu = function (viewer) {
            Autodesk.Viewing.Extensions.ViewerObjectContextMenu.call(this, viewer);
        };

        Autodesk.ADN.Viewing.Extension.MarkUpContextMenu.prototype = Object.create(Autodesk.Viewing.Extensions.ViewerObjectContextMenu.prototype);

        Autodesk.ADN.Viewing.Extension.MarkUpContextMenu.prototype.constructor = Autodesk.ADN.Viewing.Extension.MarkUpContextMenu;

        // _self.viewer.setContextMenu(new Autodesk.ADN.Viewing.Extension.MarkUpContextMenu(_self.viewer));

        viewer.addEventListener(Autodesk.Viewing.EXPLODE_CHANGE_EVENT,_self.onExplode);
        viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT, _self.onCameraChanged);
        _self.createOverlay(function(overlay) {
            _self.overlay = overlay;
        });

        activateAnnotate();

        console.log("Autodesk.ADN.Viewing.Extension.Annotation loaded");

        addToolbar();

        return true;
    };

    _self.unload = function () {

        $(viewer.container).unbind("click", _self.onMouseClick);

        var panel = new Autodesk.Viewing.Extensions.ViewerPropertyPanel(
            viewer);

        viewer.setPropertyPanel(panel);

        $('#' +  _propComboId).remove();

        console.log("Annotation unloaded");

        return true;
    };

    ///////////////////////////////////////////////////////////////////////////
    // creates new markup
    //
    ///////////////////////////////////////////////////////////////////////////
    function newMarkUp(attachmentPoint, pointImgUrl=publicPath+'/image/drawing_label/map_icon_1.png', mid, text, deleteActive, shareActive) {

        var divId = guid();

        //小红原点，点击物体的时候出现的
        //Raphaël js
        //Raphaël is a small JavaScript library that should simplify your work with vector graphics on the web 
        // var connector = _self.overlay.circle(
        //     0, 0, 10.0);
        // connector.attr("fill", "red");
        // connector.click(function(){
        //     if(clickFunction){
        //         clickFunction();
        //     }else{
        //         _self.setDetailViewVisibility(!_currentMarkUp.isVisible);
        //     }
        // })

        var connector = _self.overlay.image(pointImgUrl, 0, 0, 20, 31);
        connector[0].style['pointer-events'] = 'all';

        var content = $(_contentDiv);
        content.attr('id',divId);
        console.log('content',content)
        $('#overlayDivId').append(content);
        
        var markUp = {
            divId: divId,
            content: content,
            connector: connector,
            attachmentPoint: attachmentPoint,
        };
        
        contentEvent(divId);

        (function(divid,connector){
            let content = $('#'+ divid);
            connector.click(()=>{
                if(content.css('display') == 'none'){
                    content.css('display','');
                }else{
                    content.css('display','none');
                }
            });
        })(divId,connector);

        function contentEvent(divid){
            var textarea = $('#'+ divid).children('textarea');
            var submitBtn = $('#'+ divid).children('div').children('#submit');
            var shareBtn = $('#'+ divid).children('div').children('#share');
            var deleteBtn = $('#' + divid).children('div').children('#delete');

            submitBtn.bind('click',()=>{
                // submitBtn.css('visibility', 'hidden');
                submitBtn.attr("disabled", true);
                submitBtn.addClass("disabled");
                textarea.attr("readonly", true);

                var data = {};
                data.text = textarea.val();
                let markupTemp = _self._markUps[divid];
                data.x = markupTemp.attachmentPoint.x;
                data.y = markupTemp.attachmentPoint.y;
                data.z = markupTemp.attachmentPoint.z || 0; 
                data.divId = divid;

                _self.AddNewMarkupDelegate(data, (id, divId, formattedText) => {
                    if(id == undefined || divId == undefined || formattedText == undefined){
                        submitBtn.attr("disabled", false);
                        submitBtn.css("color", "#fffff");
                        submitBtn.removeClass("disabled");
                        textarea.attr("readonly", false);
                    }else{
                        $('#' + divId).attr('mid', id);
                        shareBtn.attr("disabled", false);
                        shareBtn.css("color", "#fffff");
                        shareBtn.removeClass("disabled");
                        textarea.val(formattedText);
                    }
                });
            });

            shareBtn.bind('click',()=>{
                _self.ShareMarkupDelegate($('#'+ divid).attr('mid'));
            })

            deleteBtn.bind('click', ()=>{
                if($('#'+ divid).attr('mid') != undefined){
                    _self.DeleteMarkupDelegate($('#'+ divid).attr('mid'), divid, (dividd) => {
                        _self.deleteMarkUpByDivId(dividd);
                    });
                }else{
                    _self.deleteMarkUpByDivId(divid);
                }
            });

            textarea.bind('click', ()=>{
                if($('#'+ divid).attr('mid') != undefined){
                    $('#overlayDivId').append($('#'+ divid));
                }
            })
            
            if(mid == undefined){
                shareBtn.attr("disabled",true);
                shareBtn.addClass("disabled");
            }else{
                //submitBtn.css("visibility", 'hidden');
                textarea.attr("readonly", true);
                submitBtn.attr("disabled",true);
                submitBtn.addClass("disabled");
            }

            if(deleteActive == '0'){
                deleteBtn.attr("disabled", true);
                deleteBtn.addClass("disabled");
            }

            if(shareActive == '0'){
                shareBtn.attr("disabled", true);
                shareBtn.addClass("disabled");
            }
        }

        $('#'+ divId).children('textarea').val(text);
        $('#'+ divId).attr('mid', mid);
        // content.appendTo($('#overlayDivId'));
        
        return markUp;
    }

    _self.GetAllMarkUpIds = function(){
        var rs = [];
        for(var i in _self._markUps){
            let mid = $('#'+ i).attr('mid');
            if(mid != undefined || mid != ''){
                rs.push(mid);
            }
        }
        return rs;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Add New Markup Delegate
    // data : 
    //      .divId : div id
    //      .x : x
    //      .y : y
    //      .z : z
    //      .text : text
    // callback : after add sync, return markup id and divid
    ///////////////////////////////////////////////////////////////////////////
    _self.AddNewMarkupDelegate = (data, callback)=> {};

    ///////////////////////////////////////////////////////////////////////////
    // Share Markup Delegate
    //id : markup id
    ///////////////////////////////////////////////////////////////////////////
    _self.ShareMarkupDelegate = (id)=> {};

    ///////////////////////////////////////////////////////////////////////////
    // Delete Markup Delegate
    //id : markup id
    //divId : div id
    //callback : after delete sync in background, need parameter divId.
    ///////////////////////////////////////////////////////////////////////////
    _self.DeleteMarkupDelegate = (id, divId, callback)=> {};

    ///////////////////////////////////////////////////////////////////////////
    // Delete All Markup Delegate

    //callback : after delete sync in background, need parameter ids, array.
    ///////////////////////////////////////////////////////////////////////////
    _self.DeleteAllMarkupDelegate = (callback) => {}

    ///////////////////////////////////////////////////////////////////////////
    // delete a markUp
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.deleteMarkUp = function(markUp) {

        $('#' + markUp.divId).remove();

        markUp.connector.remove();

        delete _self._markUps[markUp.divId];
    }

    _self.deleteAll = function(){
        for(var i in _self._markUps){
            _self.deleteMarkUp(_self._markUps[i]);
        }
    }

    _self.deleteMarkUpByDivId = function(divId){
        if(_self._markUps[divId] != undefined){
            _self.deleteMarkUp(_self._markUps[divId]);
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // mouse click callback
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.onMouseClick = function(event) {

        var screenPoint = {
            x: event.clientX,
            y: event.clientY
        };

        var n = _self.normalizeCoords(screenPoint);

        var hitPoint = viewer.impl.intersectGround(n.x, n.y);
        // var hitPoint = viewer.utilities.getHitPoint(
        //     n.x,
        //     n.y);

        if (hitPoint) {

            if(_currentMarkUp == null){
                _currentMarkUp = newMarkUp();
                _markUps[_currentMarkUp.divId] = _currentMarkUp;
            }

            var markUp = _currentMarkUp;

            markUp.attachmentPoint = hitPoint;                    

            markUp.textPos = screenPoint;                      

            _self.updateMarkUp(markUp);    

            _markUps[_currentMarkUp.divId] = _currentMarkUp;

            _self.disableEdit();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // world -> screen coords conversion
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.worldToScreen = function(worldPoint, camera) {

        var p = new THREE.Vector4();

        p.x = worldPoint.x;
        p.y = worldPoint.y;
        p.z = worldPoint.z;
        p.w = 1;

        p.applyMatrix4(camera.matrixWorldInverse);
        p.applyMatrix4(camera.projectionMatrix);

        // Don't want to mirror values with negative z (behind camera)
        // if camera is inside the bounding box,
        // better to throw markers to the screen sides.
        if (p.w > 0)
        {
            p.x /= p.w;
            p.y /= p.w;
            p.z /= p.w;
        }

        // This one is multiplying by width/2 and â€“height/2,
        // and offsetting by canvas location
        var point = viewer.impl.viewportToClient(p.x, p.y);

        // snap to the center of the pixel
        point.x = Math.floor(point.x) + 0.5;
        point.y = Math.floor(point.y) + 0.5;

        return point;
    }

    ///////////////////////////////////////////////////////////////////////////
    // screen to world coordinates conversion
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.screenToWorld = function(event) {

        var screenPoint = {
            x: event.clientX,
            y: event.clientY
        };

        var viewport =
            viewer.navigation.getScreenViewport();

        var n = {
            x: (screenPoint.x - viewport.left) / viewport.width,
            y: (screenPoint.y - viewport.top) / viewport.height
        };

        return viewer.navigation.getWorldPoint(n.x, n.y);
    }

    _self.normalizeCoords = function(screenPoint) {

        var viewport =
            viewer.navigation.getScreenViewport();

        var n = {
            x: (screenPoint.x - viewport.left),
            y: (screenPoint.y - viewport.top)
        };

        return n;
    }

    ///////////////////////////////////////////////////////////////////////////
    // camera changed callback
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.onCameraChanged = function(event) {
        // console.log(_markUps);
        _self.updateMarkUps();
    };

    ///////////////////////////////////////////////////////////////////////////
    // explode changed callback
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.onExplode = function(event) {
        _self.updateMarkUps();
    };

    ///////////////////////////////////////////////////////////////////////////
    // update markUp graphics
    //
    ///////////////////////////////////////////////////////////////////////////
    _self.updateMarkUp = function(markUp) {

        var attachmentPoint = markUp.attachmentPoint;
        var screenPoint = _self.worldToScreen(attachmentPoint, viewer.getCamera());
        markUp.screenPoint = screenPoint;
        markUp.connector.attr({
            x: screenPoint.x - 10,
            y: screenPoint.y - 31
        });

        var cw = parseInt(markUp.content.css('width'));
        var ch = parseInt(markUp.content.css('height'));


        markUp.content.css({
            left: screenPoint.x - cw / 2 - 5,
            top: screenPoint.y - ch - 40
        })

        
    };

    _self.updateMarkUps = function() {
        for(var key in _markUps){
            _self.updateMarkUp(_markUps[key]);
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // create overlay 2d canvas                                              //
    ///////////////////////////////////////////////////////////////////////////
    _self.createOverlay = function (callback) {

        if (typeof Raphael === 'undefined') {
            callback(null);
        }

        var overlayDiv = document.createElement("div");

        overlayDiv.id = 'overlayDivId';

        viewer.container.appendChild(
            overlayDiv);

        overlayDiv.style.top = "0";
        overlayDiv.style.left = "0";
        overlayDiv.style.right = "0";
        overlayDiv.style.bottom = "0";
        overlayDiv.style.position = "absolute";
        overlayDiv.style.pointerEvents = "none";
        overlayDiv.style.display = '';

        var overlay = new Raphael(
            overlayDiv,
            overlayDiv.clientWidth,
            overlayDiv.clientHeight);

        callback(overlay);
    }



    ///////////////////////////////////////////////////////////////////////////
    // Generate GUID
    //
    ///////////////////////////////////////////////////////////////////////////
    function guid() {

        var d = new Date().getTime();

        var guid = 'xxxx-xxxx-xxxx-xxxx-xxxx'.replace(
            /[xy]/g,
            function (c) {
                var r = (d + Math.random() * 16) % 16 | 0;
                d = Math.floor(d / 16);
                return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
            });

        return guid;
    }  

    ///////////////////////////////////////////////////////////////////////////
    // dynamic css styles
    //
    ///////////////////////////////////////////////////////////////////////////
    var css = [

        'canvas.graph {',
        'top:10px;',
        'left:30px;',
        'width:300px;',
        'height:300px;',
        'position:absolute;',
        'overflow:hidden;',
        '}',

        'div.chart-dropdown {',
        'position: absolute;',
        '}',

        '.scrollable-menu {',
        'height: auto;',
        'max-height: 300px;',
        'overflow-x: hidden;',
        'overflow-y: scroll;',
        '}',

    ].join('\n');

    // $('<style type="text/css">' + css + '</style>').appendTo('head');

    var style = document.createElement('style');
    style.innerHTML = css;
    var head = document.head || document.getElementsByTagName('head')[0];
    head.appendChild(style);

    // var dom = "<style type=\"text/css\">' + css + '</style>";
    // dom.appendTo('head');
    return _self;


    ///////////////////////////////////////////////////////////////////////////
    // Toolbar Customization
    //
    ///////////////////////////////////////////////////////////////////////////
    function addToolbar(){			

        var viewerToolbar = viewer.getToolbar(true);

        var ctrlGroup = new Autodesk.Viewing.UI.ControlGroup(
        "Autodesk.ADN.Viewing.Extension.Toolbar.ControlGroup");
        var buttonAdd = createButton(
        'Autodesk.ADN.Viewing.Extension.Toolbar.ControlGroupBtn',
        'url('+publicPath+'/image/drawing_label/add1.png)',
        '增加批注',
        todo);

        

        function todo(){
            _self.enableEdit();
        }

        var buttonDelete = createButton(
            'Autodesk.ADN.Viewing.Extension.Toolbar.ControlGroupBtn1',
            'url('+publicPath+'/image/drawing_label/delete.png)',
            '删除所有批注',
            ()=>{
                _self.DeleteAllMarkupDelegate((ids)=> {
                    for(var i in _self._markUps){
                        let mid = $('#'+ i).attr('mid');
                        if(mid != undefined || mid != ''){
                            if(ids.indexOf(mid) != -1){
                                _self.deleteMarkUpByDivId(i);
                            }
                        }
                    }
                })
            });



        function createButton(id, imgUrl, tooltip, handler) {
            var button = new Autodesk.Viewing.UI.Button(id);
            button.icon.style.backgroundImage = imgUrl;
            button.icon.style["background-size"] = "100% 100%";
            button.icon.style["background-repeat"] = 'no-repeat';
            button.setToolTip(tooltip);
            button.onClick = handler;
            return button;
        }

        var buttonShowHide = createRadioButton(
        'Autodesk.ADN.Viewing.Extension.Toolbar.createRadioButton',
        'url('+publicPath+'/image/drawing_label/hide.png)',
        'url('+publicPath+'/image/drawing_label/show.png)',
        '隐藏批注',
        '显示批注',
        OverlayVisibleToggle
        );

        function createRadioButton(id, imgUrl1, imgUrl2, tooltip1, tooltip2, handler) {
            var isOn = true;
            var button = new Autodesk.Viewing.UI.Button(id);
            button.icon.style.backgroundImage = imgUrl1;
            button.icon.style["background-size"] = "100% 100%";
            button.icon.style["background-repeat"] = 'no-repeat';
            button.setToolTip(tooltip1);

            button.onClick = buttonClickHandler;

            function buttonClickHandler(event){
                isOn = !isOn;
                if(isOn){
                    button.icon.style.backgroundImage = imgUrl1;
                    button.setToolTip(tooltip1);
                }else{
                    button.icon.style.backgroundImage = imgUrl2;
                    button.setToolTip(tooltip2);
                }
                if(handler != undefined && handler != null){
                    handler();
                }
            }
            return button;
        }

        ctrlGroup.addControl(buttonAdd);
        ctrlGroup.addControl(buttonShowHide);
        ctrlGroup.addControl(buttonDelete);


        viewerToolbar.addControl(ctrlGroup);
    }

    function OverlayVisibleToggle(){
        if(document.getElementById('overlayDivId').style.display == ''){
            document.getElementById('overlayDivId').style.display = 'none';
        }else{
            document.getElementById('overlayDivId').style.display = '';
        }
    }
}